#include "TcpServer.h"
#include "TcpConnection.h"
#include "Channel.h"
// #include "Log/Logging.h"
#include "Socket.h"
#include "EventLoop.h"
#include "EventLoopThreadPool.h"
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>  // snprintf
#include <memory>

using namespace std::placeholders;

void defalutTimercallback() {

}

TcpServer::TcpServer(EventLoop* loop, int port)
	: loop_(loop),
	threadPool_(new EventLoopThreadPool(loop)),
	name_("connection"),
	listenSocket_( new Socket(createNonblockingSocket())),
	started_(false),
	nextConnId_(0),
	port_(port)
{
	listenSocket_->bindAddress(port_);
	listenSocket_->setReuseAddr(true);
	listenSocket_->setKeepAlive(true);
	acceptor_ = std::make_shared<Channel>(loop, listenSocket_->fd());
	acceptor_->setReadCallback(std::bind(&TcpServer::handleNewConnection, this));
	acceptor_->enableReading();
}

TcpServer::~TcpServer() {

}

void TcpServer::setThreadNum(int numThreads)
{
  assert(0 <= numThreads);
  threadPool_->setThreadNum(numThreads);
}

void TcpServer::start() {
	// 启动线程池
	threadPool_->start();
	// 创建监听套接字 开始监听
	std::cout << "listening" << std::endl;
	listenSocket_->listening();

}

void TcpServer::newConnection(int sockfd) {
	char buf[32];
	snprintf(buf, sizeof buf, "#%d", nextConnId_);
	++nextConnId_;
	std::string connName = name_ + buf;

	// 从池中取出一个EventLoop
	EventLoop* ioLoop = threadPool_->getNextLoop();
	// cout << "nextConnId: " + to_string(nextID()) + " sockfd: " + to_string(sockfd) + "\n";

	TcpConnectionPtr conn( new TcpConnection(ioLoop, connName, sockfd) );
	connections_[connName] = conn;
	conn->setConnectionCallback(connectionCallback_);
	conn->setMessageCallback(messageCallback_);
	// conn->setWriteCompleteCallback(writeCompleteCallback_);
	conn->setCloseCallback( std::bind(&TcpServer::removeConnection, this, _1) );
	ioLoop->runInLoop(std::bind(&TcpConnection::connectEstablished, conn));
}

void TcpServer::removeConnection(const TcpConnectionPtr& conn) {
	loop_->runInLoop(std::bind(&TcpServer::removeConnectionInLoop, this, conn));
}

void TcpServer::removeConnectionInLoop(const TcpConnectionPtr& conn)
{
	loop_->assertInLoopThread();
	size_t n = connections_.erase(conn->name());
	EventLoop* ioLoop = conn->getLoop();
	ioLoop->queueInLoop(std::bind(&TcpConnection::connectDestroyed, conn));
}

// 调用accept
// 可以修改为循环accept知道没有新连接 适合短连接服务
void TcpServer::handleNewConnection() {
	loop_->assertInLoopThread();
	while (1) {
		int connfd = listenSocket_->accept();
		if (connfd > 0) {
			if (connfd > 4000) {
				close(connfd);
				continue;
			}
			newConnection(connfd);
		} 
		else {
			break;
		}
	}
}

